home *** CD-ROM | disk | FTP | other *** search
- /*
- * M S G 2 . C
- *
- * This is the second part of the MSG program.
- *
- * Functions -
- * rdnxtfld read next field from input
- * prhdr print header on stdout
- * hdrfile print header on outfp
- * hdrout print header on specified FILE p
- * gomsg goto a specific message
- * delmsg delete specified message
- * undelmsg un-delete specified message
- * keepmsg mark specified message for keeping
- * getfn
- * cpyiter
- * cppipe
- * cpopen
- * dolstmsg list the selected messages, maybe separated
- * lstmsg list one message, maybe separated
- * lstbdy list body of one message
- * movmsg "move" a message
- * putmsg "put" a message
- * writmsg write specified message onto given FD
- * writbdy write body of specified message onto given FD
- * prmsg print specified message onto terminal
- * ansiter top-level iteration for "answer"
- * ansqry enquire who to send answer to
- * ansmsg create header for answer
- * fwditer top-level iteration for "forward"
- * fwdmsg copy one forwarded message, with markers
- * fwdpost add trailer to forwarded message
- * srchkey Keyword search for stripping obnoxious header lines.
- * filout Filters control characters before writing on terminal.
- * makedrft Make a file containing one or more messages
- *
- * R E V I S I O N H I S T O R Y
- *
- * 06/08/82 MJM Split the enormous MSG program into pieces.
- *
- * 09/10/82 MJM Modified to use STDIO for output to files, too.
- *
- * 11/14/82 HW Added keyword filter to ignore Via, Remailed, etc.
- */
- #include "util.h"
- #include "mmdf.h"
- #include <pwd.h>
- #include <signal.h>
- #include <sys/stat.h>
- #include <sgtty.h>
- #include "./msg.h"
-
- extern FILE *popen();
-
- /*
- * R D N X T F L D
- *
- * read next field from input
- */
- rdnxtfld()
- {
- register char c;
-
- do {
- c = ttychar();
- } while( (isspace( c) || c == ch_erase) && c != '\n' );
-
- return(c);
- }
-
- /*
- * P R H D R
- */
- prhdr()
- {
- hdrout( stdout, TRUE);
- }
-
- /*
- * H D R F I L E
- */
- hdrfile()
- {
- hdrout( outfp, FALSE);
- }
-
-
-
-
- hdrout( fp,crflag)
- FILE *fp;
- int crflag;
- {
- char lbuf[LINESIZE];
-
- sprintf( lbuf, "%4d%c%c%c%c%c%c%5ld: %-9.9s %-15.15s %.30s%s\n",
- msgno,
- mptr->flags & M_NEW ? 'N' : ' ',
- mptr->flags & M_DELETED ? 'D' : ' ',
- mptr->flags & M_KEEP ? 'K' : ' ',
- mptr->flags & M_ANSWERED ? 'A' : ' ',
- mptr->flags & M_FORWARDED ? 'F' : ' ',
- mptr->flags & M_PUT ? 'P' : ' ',
- mptr->len,
- mptr->datestr,
- mptr->from,
- mptr->subject,
- crflag ? "\r" : ""
- );
- filout( lbuf, fp );
- }
-
- /*--------------------------------------------------------------------*/
-
- gomsg()
- {
- status.ms_curmsg = msgno; /* set the current message number */
- }
-
- delmsg()
- {
- mptr->flags |= M_DELETED;
- mptr->flags &= ~M_KEEP;
- }
-
- undelmsg()
- {
- mptr->flags &= ~(M_DELETED|M_KEEP);
- }
-
- keepmsg()
- {
- mptr->flags |= M_KEEP;
- mptr->flags &= ~M_DELETED;
- }
-
- /*
- * G E T F N
- *
- * Get a file name for the user.
- */
- getfn( s, f, def)
- char *s; /* Prompt string to provoke user */
- char *f; /* place to put resulting answer */
- char *def; /* optional default */
- {
- char tmpbuf[LINESIZE];
- char name[LINESIZE];
- struct passwd *getpwuid(), *getpwnam();
- register char *t, *n;
- register struct passwd *pw;
-
- tt_norm();
- fputs( s, stdout);
- fflush( stdout);
-
- strcpy( oldfile, f);
-
- if( gets( tmpbuf) == NULL || isnull( tmpbuf[0])) {
- if( def == (char *)0)
- error( "no filename specified\r\n");
- else {
- strcpy( f, def);
- printf( "%s...\r\n", f);
- }
- } else {
- /* Remove leading whitespace */
- for( t = tmpbuf; isspace(*t); t++ )
- ;
- if( *t == '~' ) {
- /* Expand */
- for( n = name; *++t && *t != '/'; *n++ = *t )
- ;
- *n = '\0';
- if( name[0] == '\0' )
- pw = getpwuid(getuid());
- else
- pw = getpwnam(name);
- if( pw == NULL )
- error("~name not found\r\n");
- (void) strcpy(f, pw->pw_dir);
- (void) strcat(f, t);
- } else
- strcpy(f, t);
- }
-
- nxtchar = '\n'; /* note the last character typed */
- tt_raw();
- }
-
- /*
- * C P Y I T E R
- */
- cpyiter( fn, iterfl, post)
- int ( *fn)(); /* per-message function */
- int iterfl; /* To iterate or not to iterate */
- int ( *post)(); /* post-process function */
- {
- if( outfile[0] == '|') /* output filter, not file */
- cppipe(); /* get the output pipe */
- else
- cpopen(); /* get the output file */
-
- tt_norm();
- if( iterfl == DOIT )
- doiter( fn);
- else
- (*fn)();
- tt_norm();
-
- if(post != 0)
- (*post)();
-
- if(outfile[0] == '|') { /* collect the child */
- pclose( outfp ); /* done sending to file/pipe */
- signal( SIGINT, onint );
- } else
- lk_fclose (outfp, outfile, NULL, NULL);
-
- outfd = -1;
- tt_raw();
- }
-
- /*
- * C P P I P E
- */
- cppipe()
- {
- char buf[LINESIZE];
-
- fflush(stdout);
- if ((outfp = popen(&outfile[1], "w")) == NULL)
- error( "problem starting pipe command\r\n");
-
- outfd = -1;
- return;
- }
-
- /*
- * C P O P E N
- *
- * open a file to copy into
- */
- cpopen()
- {
-
- /* EXCLUSIVE open the file, as we are writing */
- if( (outfd = lk_open( outfile, 1, (char *)0, (char *)0, 5)) < 0) {
- switch( errno) {
- case ENOENT:
- if( !autoconfirm) {
- printf( "Create '%s'", outfile);
- if( !confirm((char *)0,DOLF))
- error( "");
- }
- if( (outfd = creat( outfile, sentprotect)) < 0) {
- printf( "can't create '%s'", outfile);
- error( "\r\n");
- }
-
- close( outfd);
- /* EXCLUSIVE open, since writing */
- if( (outfd = lk_open( outfile, 1, (char *)0, (char *)0, 5)) < 0) {
- printf( "can't open '%s'", outfile);
- error( "\r\n");
- }
- break;
-
- case ETXTBSY:
- printf( "'%s' is busy; try later", outfile);
- error( "\r\n");
-
- default:
- perror(outfile);
- error( "\r");
- }
- }
-
- /*
- * Set up for STDIO output using the exclusive
- * write-only FD. The fclose( outfd ) will flush
- * the buffers. The "a" append is necessary in
- * the event that the file already exists.
- */
- if( (outfp = fdopen( outfd, "a" )) == NULL ) {
- error( "can't fdopen outfile\n" );
- outfd = -1;
- }
- }
-
- /*
- * D O L S T M S G
- *
- * list the selected messages, maybe separated
- */
- dolstmsg()
- {
- doiter ( lstmsg);
- }
-
- /*
- * L S T M S G
- *
- * list one message, maybe separated
- */
- lstmsg()
- {
- if( lstsep && lstmore)
- fputs( "\f\n", outfp );
- lstmore = TRUE;
-
- if( prettylist) {
- fprintf(outfp, "(Message # %d: %ld bytes", msgno, mptr->len );
- if( mptr->flags & M_DELETED ) fprintf(outfp, ", Deleted");
- if( mptr->flags & M_PUT ) fprintf(outfp, ", Put");
- if( mptr->flags & M_NEW ) fprintf(outfp, ", New");
- if( mptr->flags & M_KEEP ) fprintf(outfp, ", KEEP");
- if( mptr->flags & M_ANSWERED ) fprintf(outfp, ", Answered");
- if( mptr->flags & M_FORWARDED ) fprintf(outfp, ", Forwarded");
- fprintf(outfp, ")\n");
- }
-
- writmsg();
- mptr->flags &= ~M_NEW; /* Message seen */
- }
-
- /*
- * L S T B D Y
- *
- * list one message body, maybe separated
- */
- lstbdy()
- {
- if( lstsep && lstmore)
- fputs( "\f\n", outfp );
- lstmore = TRUE;
-
- writbdy();
- mptr->flags &= ~M_NEW; /* Message seen */
- }
-
- /*
- * M O V M S G
- */
- movmsg()
- {
- putmsg();
- delmsg();
- }
-
- /*
- * P U T M S G
- */
- putmsg()
- {
- register int len;
-
- len = strlen( delim1);
- fwrite( delim1, sizeof(char), len, outfp );
- writmsg();
- fwrite( delim2, sizeof(char), len, outfp );
- mptr->flags |= M_PUT;
- }
-
- /*
- * W R I T M S G
- */
- writmsg()
- {
- long size;
- int count;
- char tmpbuf[512];
-
- fseek( filefp,( long)( mptr->start), 0);
- for( size = mptr->len; size > 0; size -= count) {
- if( size <( sizeof tmpbuf))
- count = size;
- else
- count =( sizeof tmpbuf);
-
- if( fread( tmpbuf, sizeof( char), count, filefp) < count)
- error( "error reading\r\n");
- if( fwrite( tmpbuf, sizeof(char), count, outfp ) < count )
- error( "error writing to file\r\n");
- }
- }
-
- /*
- * W R I T B D Y
- */
- writbdy()
- {
- long size;
- int srcstat;
- char line[LINESIZE];
-
- fseek( filefp,( long)( mptr->start), 0);
- size = mptr->len;
-
- srcstat = SP_HNOSP;
- while( size > 0) {
- if( xfgets( line, sizeof( line), filefp) == NULL )
- break;
- size -= strlen( line );
-
- if( srcstat == SP_HNOSP && *line == '\n' ) {
- /* Don't output the separating blank line */
- srcstat = SP_BODY;
- continue;
- }
-
- if( srcstat == SP_BODY )
- fputs( line, outfp );
-
- }
- }
-
- /*
- * P R M S G
- */
- prmsg()
- {
- char line[LINESIZE];
- register long size;
- int srcstat;
-
- tt_norm();
-
- size = mptr->len;
- status.ms_curmsg = msgno;
-
- printf( "(Message # %d: %ld bytes", msgno, size );
- if( mptr->flags & M_DELETED ) printf(", Deleted");
- if( mptr->flags & M_PUT ) printf(", Put");
- if( mptr->flags & M_NEW ) printf(", New");
- if( mptr->flags & M_KEEP ) printf(", KEEP");
- if( mptr->flags & M_ANSWERED ) printf(", Answered");
- if( mptr->flags & M_FORWARDED ) printf(", Forwarded");
- printf(")\n");
- fflush( stdout );
-
- if(quicknflag == ON )
- mptr->flags &= ~M_NEW; /* Message seen */
-
- fseek( filefp,( long)( mptr->start), 0);
-
- srcstat = SP_HNOSP;
- while( size > 0) {
- if( xfgets( line, sizeof( line), filefp) == NULL )
- break;
-
- if( *line == '\n' )
- srcstat = SP_BODY;
- /* filter obnoxious lines */
- if( keystrip == ON && srcstat != SP_BODY ) {
- if( !(srcstat == SP_HSP &&
- (*line == '\t' || *line == ' ')))
- if( srchkey( line, keywds) == 0 ) {
- filout( line, stdout );
- srcstat = SP_HNOSP;
- }
- else
- srcstat = SP_HSP;
- }
- else
- filout( line, stdout);
-
- size -= strlen( line );
- }
- tt_raw();
- mptr->flags &= ~M_NEW; /* Message seen */
- }
-
- /*--------------------------------------------------------------------*/
-
- /*
- * A N S I T E R
- *
- * Top level for "answer" command.
- */
- ansiter()
- {
- sndto[0] =
- sndcc[0] =
- sndsubj[0] = '\0';
- ansnum = 0;
-
- doiter( prhdr);
- anstype = ansqry();
-
- doiter( ansmsg);
-
- if( ansnum == 0)
- printf( "no messages to answer\r\n");
- else
- if( isnull( sndto[0]))
- printf( "no From field in header\r\n");
- else {
- xeq( 'a'); /* execute an answer command */
- doiter( ansend ); /* Set the A flag */
- }
- }
-
- /*
- * E D A N S I T E R
- *
- * Top level for "answer" command, to drop into EMACS 2-window mode.
- */
- edansiter()
- {
- register int fd;
-
- sndto[0] =
- sndcc[0] =
- sndsubj[0] = '\0';
- ansnum = 0;
-
- doiter( prhdr);
- anstype = ansqry();
-
- doiter( ansmsg);
-
- if( ansnum == 0) {
- printf( "no messages to answer\r\n");
- return;
- }
- if( isnull( sndto[0]) ) {
- printf( "no From field in header\r\n");
- return;
- }
-
- /* Prepare the work files */
- if( (fd = creat(draft_work, sentprotect)) < 0 ) {
- perror( draft_work );
- return;
- }
- close(fd);
-
- makedrft();
-
- /* Invoke EDITOR in 2-window mode */
- xeq( 'e' );
-
- /* Feed results into SEND */
- xeq( 'A' );
-
- /* Set the A flag */
- doiter( ansend );
-
- /* Clean up */
- unlink( draft_original );
- /* draft_work left behind in case he wants another look at it */
- }
-
- /*
- * A N S Q R Y
- * who to send answer to
- */
- ansqry()
- {
-
- again:
- printf( "copies to which original addresses: ");
- nxtchar = echochar();
- nxtchar = uptolow( nxtchar);
-
- switch( nxtchar) {
-
- case '\n':
- case '\r':
- if( verbose)
- printf( "from\r\n");
- return( ANSFROM);
-
- case 'a':
- if( verbose)
- printf( "ll\r\n");
- return( ANSALL);
-
- case 'c':
- if( verbose)
- printf( "c'd\r\n");
- return( ANSCC);
-
- case 'f':
- if( verbose)
- printf( "rom\r\n");
- return( ANSFROM);
-
- case 't':
- if( verbose)
- printf( "o\r\n");
- return( ANSTO);
-
- case '?':
- if( verbose)
- printf( "\r\n");
- printf( "all\r\n");
- printf( "cc'd\r\n");
- printf( "from [default]\r\n");
- printf( "to\r\n");
- goto again;
-
- case '\004':
- default:
- error( " ?\r\n");
- }
- /* NOTREACHED */
- }
-
-
- /*
- * A N S M S G
- *
- * get create To, & Subject fields
- */
- ansmsg()
- {
- char tmpfrom[M_BSIZE],
- tmprply[M_BSIZE],
- tmpsender[M_BSIZE],
- tmpto[M_BSIZE],
- tmpcc[M_BSIZE],
- tmpsubj[M_BSIZE];
- register unsigned int ind;
- int llenleft;
-
- ansnum++;
- status.ms_curmsg = msgno;
-
- tmpfrom[0] =
- tmprply[0] =
- tmpsender[0] =
- tmpto[0] =
- tmpcc[0] =
- tmpsubj[0] = '\0';
-
- gethead( NODATE, tmpfrom, tmpsender, tmprply,
- (anstype & ANSTO) ? tmpto : NOTO,
- (anstype & ANSCC) ? tmpcc : NOCC, tmpsubj);
-
- if( !isnull( tmprply[0]))
- /* send to Reply-To */
- sprintf( &sndto[strlen( sndto)], ",%s%c", tmprply, '\0');
- else if( !isnull( tmpfrom[0]))
- /* send to From, if no Reply-To */
- sprintf( &sndto[strlen( sndto)], ",%s%c", tmpfrom, '\0');
-
- if( !isnull( tmpto[0]))
- sprintf( &sndcc[strlen( sndcc)], ",%s%c", tmpto, '\0');
-
- if( !isnull( tmpcc[0]))
- sprintf( &sndcc[strlen( sndcc)], ",%s%c", tmpcc, '\0');
-
- if( !isnull( tmpsubj[0])) {
- /* save the destination */
- if( equal( "re:", tmpsubj, 3))
- for( ind = 3; isspace( tmpsubj[ind]); ind++);
- else
- if( equal( "reply to:", tmpsubj, 9))
- for( ind = 9; isspace( tmpsubj[ind]); ind++);
- else
- ind = 0;
-
- if( ansnum == 1)
- /* not the first message */
- sprintf( sndsubj, "Re: %s%c", &tmpsubj[ind], '\0');
- else {
- /* append more addresses */
- if( (llenleft = sizeof(sndsubj) - strlen(sndsubj))
- -strlen(&tmpsubj[ind])-9 > 0 )
- sprintf( &sndsubj[strlen( sndsubj)],
- "\n %s%c", &tmpsubj[ind], '\0');
- else if( llenleft > 7 )
- sprintf( &sndsubj[strlen( sndsubj)],
- "\n...%c", '\0');
- }
- }
- }
- /*--------------------------------------------------------------------*/
- ansend() { /* Set the A flag */
-
- mptr->flags |= M_ANSWERED;
- }
- /*--------------------------------------------------------------------*/
- /*
- * F W D I T E R
- *
- * Top level for forward command.
- */
- fwditer()
- {
- char *mktemp();
-
- status.ms_curmsg = msgno;
- fwdnum = 0;
- sndto[0] =
- sndcc[0] =
- sndsubj[0] = '\0';
-
- doiter( prhdr);
-
- strcpy( outfile, "/tmp/send.XXXXXX");
- mktemp( outfile);
-
- autoconfirm = TRUE;
- cpyiter( fwdmsg, DOIT, fwdpost);
- autoconfirm = FALSE;
-
- xeq( 'f');
- unlink( outfile);
- }
-
- /*
- * F W D M S G
- *
- * copy one forwarded message
- */
- fwdmsg()
- {
- char line[M_BSIZE];
- int llenleft;
-
- fwdnum++;
-
- line[0] = '\0'; /* build a subject line */
- gethead( NODATE, NOFROM, NOSNDR, NORPLY, NOTO, NOCC, line);
-
- if( !isnull( line[0])) {
- /* If we had a subject line, bracket the subject info */
- if( isnull( sndsubj[0]) )
- /* the first subject line */
- sprintf( sndsubj, "[%s: %s]%c",
- mptr->from, line, '\0');
- else {
- /* not the first line */
- if( (llenleft = sizeof(sndsubj) - strlen(sndsubj))
- -strlen(line)-SIZEFROM-10 > 0 )
- sprintf( &sndsubj[strlen( sndsubj)],
- "\n[%s: %s]%c", mptr->from, line, '\0');
- else if( llenleft > 7 )
- sprintf( &sndsubj[strlen( sndsubj)],
- "\n...%c", '\0');
-
- }
- }
-
- fprintf( outfp, "\n----- Forwarded message # %d:\n\n", fwdnum);
-
- writmsg();
-
- mptr->flags |= M_FORWARDED;
- }
-
- /*
- * F W D P O S T
- */
- fwdpost()
- {
- fprintf( outfp, "\n----- End of forwarded messages\n" );
- }
- /*
- * S R C H K E Y
- */
- srchkey( line, keypt)
- char *line, *keypt[];
- {
- register int n;
- register char *pkey, *pline;
-
- for( n = 0; keypt[n] != 0; n++ ) {
- pkey = keypt[n];
- pline = line;
-
- while( *pkey != '\0' ) {
-
- if( *pline != *pkey && *pline - 'A' + 'a' != *pkey )
- goto trynext;
- pline++;
- pkey++;
- }
- return(1);
- trynext: ;
- }
- return(0);
- }
- /* ------------------------------------------------------------------
- * F I L O U T
- *
- * Filter most control chars from text - Prevents letter bombs
- * Also does paging
- * ****** linecount must be initialized before calling filout ******
- */
- filout(line, ofp)
- char *line;
- FILE *ofp;
- {
- register int cmd;
-
- if( paging ) {
- linecount += (strlen( line ) / linelength ) + 1;
-
- if( doctrlel && strindex( "\014", line) >= 0) {
- /* Got formfeed */
- tt_raw();
- if( !confirm("Formfeed. Continue?",NOLF))
- error("");
- tt_norm();
- linecount = 0;
- }
-
- if ( linecount >= pagesize - 2) {
- tt_raw();
- if( (cmd = confirm("Continue?",NOLF)) == FALSE )
- error("");
- tt_norm();
- switch( cmd ) {
-
- case '\n': /* One more line */
- linecount = pagesize;
- break;
-
- default:
- linecount = 0;
- break;
- }
- }
- }
-
- if( filoutflag == OFF ) {
- fputs( line, ofp );
- return;
- }
-
- for( ; *line != '\000'; line++ ) {
- if( *line >= ' ' && *line <= '~' )
- putc( *line, ofp );
- else {
- switch ( *line ) {
-
- case '\007': /* Bel */
- case '\t':
- case '\n':
- case '\r':
- case '\b':
- putc( *line, ofp );
- break;
-
- default:
- putc( '^', ofp );
- putc( *line + '@', ofp );
- break;
- }
- }
- }
- }
- /*
- * M A K E D R F T
- * Make a file containing one or more messages
- */
- makedrft() {
-
- register int fd;
-
- if( (fd = creat(draft_original, sentprotect)) < 0 ) {
- perror( draft_original );
- return;
- }
- close( fd );
-
- /* LIST messages into the draft_original file */
- lstsep = TRUE;
- strcpy( outfile, draft_original );
- cpyiter( lstmsg, DOIT, (int(*)()) 0 );
-
- }
-